import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
 
public class ServClass extends Thread implements ServerListener {
 
    // Хранит онлайн пользователей чата
    public LinkedList<User> userlist;
    // Хранит слушателей сервера
    private LinkedList<ServerListener> listenerList;
    // СерверСокет
    private ServerSocket serverSocket;
 
    // Обьект синхронизации доступа
    private final Object lock = new Object();
    
    // Конструктор
    public ServClass() {
        super("ServClass");
        userlist = new LinkedList<User>();
        listenerList = new LinkedList<ServerListener>();
    }
 
    // Запускает сервер на определенном порту
    public void init(int port) {
        try {
            serverSocket = new ServerSocket(port);
            start();
            String ip = serverSocket.getInetAddress().getLocalHost().getHostAddress();
            // Нотификация события: сервер запущен
            serverStarted(ip, port);
        } catch(Exception ex) {
            // Нотификация события: cервер прекратил работу
            serverStopped();
        }
    }
 
    /********************** Обработка потока сервера ************************/
 
    @Override
    public void run() {
        while(true) {
            try {
                // Метод accept() блочит данный поток пока не подключиться новый пользователь
                Socket socket = serverSocket.accept();
                // Создание нового потока-обработчика для подключенного пользователя
                // он выполняется паралельно данному потоку, и ниче не блочит.
                // Сервер переходит к готовности принять новое соединение
                User user = new User(this, socket);
            } catch (Exception ex) {
            }
        }
    }
    
    /***************** отправка сообщения всем пользователям ****************/
    // sender - отправитель
 
    public void sendChatMessage(User sender, String message) {
        synchronized(lock) {
            for(User user : userlist) {
                try {
                    user.printStream.println("<"+(sender!=null ? sender.userName : "server")+"> "+message);
                } catch (Exception ex) {}
            }
        }
    }
 
    /******************** добавление/удаление слушателей ********************/
 
    // Добавляет слушателя событий сервера
    public void addListener(ServerListener listener) {
        synchronized(lock) {
            listenerList.add(listener);
        }
    }
 
    // Удаляет слушателя
    public void removeListener(ServerListener listener) {
        synchronized(lock) {
            listenerList.remove(listener);
        }
    }
 
    /******************** методы интерфейса ServerListener *******************/
 
    public void serverStarted(String ip, int port) {
        synchronized(lock) {
            for(ServerListener listener : listenerList) {
                listener.serverStarted(ip, port);
            }
        }
    }
 
    public void serverStopped() {
        synchronized(lock) {
            for(ServerListener listener : listenerList) {
                listener.serverStopped();
            }
        }
    }
 
    public void onUserConnected(User user) {
        synchronized(lock) {
            for(ServerListener listener : listenerList) {
                listener.onUserConnected(user);
            }
        }
    }
 
    public void onUserDisconnected(User user) {
        synchronized(lock) {
            for(ServerListener listener : listenerList) {
                listener.onUserDisconnected(user);
            }
        }
    }
 
    public void onMessageReceived(User user, String message) {
        synchronized(lock) {
             for(ServerListener listener : listenerList) {
                listener.onMessageReceived(user, message);
            }
        }
    }
 
}